#pragma once
#include "Comm.h"

namespace COMM
{
	class COMM_API SqlStatement
	{
	public:
		enum DataType
		{
			INT = 1,
			FLT = 2,
			TXT = 3,
			BLB = 4,
			NUL = 5
		};
		~SqlStatement();
		bool IsValid();
		DataType GetDataType(int index);
		int ValueInt (int index);
		long long ValueInt64(int index);
		double ValueFloat(int index);
		String ValueString(int index);
		Buffer ValueBlob(int index);

		bool Bind(int index, const void* value, int size, bool copy=true);
		bool Bind(int index, double value);
		bool Bind(int index, int value);
		bool Bind(int index, long long value);
		bool BindNull(int index);

		bool Execute();
		// do it while return true.
		bool NextRow();
		bool Reset(bool clear_bindings=false);

	private:
		friend class SqlDatabase;
		SqlStatement(const char* sql, void* db);
		void* m_db;
		void* m_stmt;
	};

	class COMM_API SqlDatabase
	{
	public:
		class COMM_API DataTable
		{
		public:
			DataTable();
			~DataTable();
			bool IsValid() const;
			int Rows() const;
			int Columns() const;
			const char** Row(int index) const;
			const char** ColumnNames() const;
			const char** operator[](int row) const;
			const char* Cell(int row,int column) const;
		private:
			friend class SqlDatabase;
			char **pazResult;
			int nRow;
			int nColumn;
		};

		SqlDatabase();
		~SqlDatabase();
		// Only Support SQLITE3 now.
		bool Open(const char* conn);
		void Close();
		bool Select(const char* sql, DataTable& dt);
		// execute one sql.
		bool Execute(const char* sql);
		// execute more than one sql.ex: "BEGIN; sql_batch; COMMIT;"
		bool ExecuteBatch(const char* sql_batch);
		// prepare only one sql.
		// return: NULL mean failure.
		SqlStatement* Prepare(const char* sql);

		// Transaction related
		bool Begin();
		bool Commit();
		bool Rollback();

	private:
		void* m_db;
	};

}

